package com.auth.manage.limiter;

import lombok.RequiredArgsConstructor;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;

@RequiredArgsConstructor
public class SlidingWindowRateLimiter {
    private final RedissonClient redissonClient;

    private static final String LIMIT_KEY_PREFIX = "auth:manage:limit:";

    /**
     * 判断一个key是否可以通过
     *
     * @param key 限流的key
     * @param limit 限流的数量
     * @param windowSize 窗口大小，单位为秒
     * @return
     */
    // 创建限流器并配置，然后进行校验
    public Boolean tryAcquire(String key, int limit, int windowSize){
        // 在本地创建了一个Java对象，没有和Redis服务做任何交互
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(LIMIT_KEY_PREFIX + key);
        // 针对rateLimiter.isExists()判断的原因：不加的后果：如果有1000个请求进来，他们都运行了这段代码，会向Redis发起999次无效的请求，消耗Redis性能
        if (!rateLimiter.isExists()){
            // 参数1：针对所有客户端，无论有多少个应用实例在调用这个RRateLimiter，它们共同分享limit所设定的配额
            // windowSize秒内，只能允许limit次请求通过
            rateLimiter.trySetRate(RateType.OVERALL, limit, windowSize, RateIntervalUnit.SECONDS);
        }
        return rateLimiter.tryAcquire();
    }

}
